wayland: Roundtrip until we've receive initial input and output configuration
authorKristian Høgsberg <krh@bitplanet.net>
Tue, 26 Mar 2013 18:42:14 +0000 (14:42 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Tue, 26 Mar 2013 18:42:16 +0000 (14:42 -0400)
We use a ref-count mechanism to track whether parts of the init sequence
still needs round trips to receive remaining initial state.  Typically
we need a couple of roundtrips total to get the global list, then the
input and output configurations, but with the ref-count we avoid making
global assumptions like that.

https://bugzilla.gnome.org/show_bug.cgi?id=696340

gdk/wayland/gdkdevice-wayland.c
gdk/wayland/gdkdisplay-wayland.c
gdk/wayland/gdkdisplay-wayland.h
gdk/wayland/gdkscreen-wayland.c

index cc942ebe0d625ddc36267aafd013a44306ab237b..aa696369fa626e645f686bf33a8f95cf03c4944d 100644 (file)
@@ -1106,6 +1106,7 @@ seat_handle_capabilities(void *data, struct wl_seat *seat,
   GdkWaylandDeviceData *device = data;
   GdkWaylandDeviceManager *device_manager =
     GDK_WAYLAND_DEVICE_MANAGER(device->device_manager);
+  GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (device->display);
 
   if ((caps & WL_SEAT_CAPABILITY_POINTER) && !device->wl_pointer)
     {
@@ -1178,6 +1179,10 @@ seat_handle_capabilities(void *data, struct wl_seat *seat,
       _gdk_device_set_associated_device (device->pointer, device->keyboard);
       _gdk_device_set_associated_device (device->keyboard, device->pointer);
     }
+
+  /* Once we have the capabilities event we know we have all events
+   * from the wl_seat and need no further init roundtrips. */
+  display->init_ref_count--;
 }
 
 static const struct wl_seat_listener seat_listener = {
index 5061f07a16c8997f4036c1d150514851a8b79e39..99707524b3c588f6a40163d61d4d0139e57140c3 100644 (file)
@@ -100,6 +100,7 @@ gdk_registry_handle_global(void *data, struct wl_registry *registry, uint32_t id
   if (strcmp(interface, "wl_compositor") == 0) {
     display_wayland->compositor =
        wl_registry_bind(display_wayland->wl_registry, id, &wl_compositor_interface, 1);
+    display_wayland->init_ref_count--;
   } else if (strcmp(interface, "wl_shm") == 0) {
    display_wayland->shm =
        wl_registry_bind(display_wayland->wl_registry, id, &wl_shm_interface, 1);
@@ -113,10 +114,18 @@ gdk_registry_handle_global(void *data, struct wl_registry *registry, uint32_t id
     output =
       wl_registry_bind(display_wayland->wl_registry, id, &wl_output_interface, 1);
     _gdk_wayland_screen_add_output(display_wayland->screen, output);
+    /* We need to roundtrip until we've received the modes and
+     * geometry events for the output, which gives us the physical
+     * properties and available modes on the output. */
+    display_wayland->init_ref_count++;
   } else if (strcmp(interface, "wl_seat") == 0) {
     seat = wl_registry_bind(display_wayland->wl_registry, id, &wl_seat_interface, 1);
     _gdk_wayland_device_manager_add_device (gdk_display->device_manager,
                                            seat);
+    /* We need to roundtrip until we've received the wl_seat
+     * capabilities event which informs us of available input devices
+     * on this seat. */
+    display_wayland->init_ref_count++;
   } else if (strcmp(interface, "wl_data_device_manager") == 0) {
       display_wayland->data_device_manager =
         wl_registry_bind(display_wayland->wl_registry, id,
@@ -164,7 +173,11 @@ _gdk_wayland_display_open (const gchar *display_name)
   display_wayland->wl_registry = wl_display_get_registry(display_wayland->wl_display);
   wl_registry_add_listener(display_wayland->wl_registry, &registry_listener, display_wayland);
 
-  wl_display_dispatch(display_wayland->wl_display);
+  /* We use init_ref_count to track whether some part of our
+   * initialization still needs a roundtrip to complete. */
+  display_wayland->init_ref_count = 1;
+  while (display_wayland->init_ref_count > 0)
+    wl_display_roundtrip(display_wayland->wl_display);
 
   display_wayland->event_source =
     _gdk_wayland_display_event_source_new (display);
index 269d447bbfc332aa08e9bcf7a1efa607c6d8a758..35eac41a3d8f6029ac3f9b747ecfca9c52f63cec 100644 (file)
@@ -66,6 +66,8 @@ struct _GdkWaylandDisplay
 
   GSource *event_source;
 
+  int init_ref_count;
+
   struct xkb_context *xkb_context;
 };
 
index 7f209b59d96c9a7ce566c3a2b1e858413d55e493..be1a0f541726d013b84ac4a8c4f127458c676fe7 100644 (file)
@@ -79,6 +79,7 @@ struct _GdkWaylandScreenClass
 
 struct _GdkWaylandMonitor
 {
+  GdkWaylandScreen *screen;
   struct wl_output *output;
   GdkRectangle  geometry;
   int          width_mm;
@@ -859,6 +860,7 @@ output_handle_geometry(void *data,
                       int32_t transform)
 {
   GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data;
+  GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (monitor->screen->display);
 
   monitor->geometry.x = x;
   monitor->geometry.y = y;
@@ -868,6 +870,10 @@ output_handle_geometry(void *data,
 
   monitor->manufacturer = g_strdup (make);
   monitor->output_name = g_strdup (model);
+
+  /* Once we have the geometry event we know we have all events
+   * from the wl_output and need no further init roundtrips. */
+  display->init_ref_count--;
 }
 
 static void
@@ -901,6 +907,7 @@ _gdk_wayland_screen_add_output (GdkScreen *screen,
   GdkWaylandMonitor *monitor = g_new0(GdkWaylandMonitor, 1);
 
   monitor->output = output;
+  monitor->screen = screen_wayland;
   g_ptr_array_add(screen_wayland->monitors, monitor);
 
   wl_output_add_listener(output, &output_listener, monitor);